//
//  UICollectionView+CJLongPressMove.m
//  TSListDemo
//
//  Created by ciyouzen on 2020/3/26.
//  Copyright © 2020 dvlproad. All rights reserved.
//

#import "UICollectionView+CJLongPressMove.h"
#import <objc/runtime.h>

static NSString * const cjCheckSectionMoveEnableBlockKey = @"cjCheckSectionMoveEnableBlockKey";
static NSString * const cjCheckCellMoveEnableBlockKey = @"cjCheckCellMoveEnableBlockKey";

@interface UICollectionView () {
    
}
@property (nonatomic, copy) BOOL (^cjCheckSectionMoveEnableBlock)(NSIndexPath *indexPath);  /**< 设置允许哪些section中的哪些item进行拖动操作，未设置则默认都允许 */
@property (nonatomic, copy) BOOL (^cjCheckCellMoveEnableBlock)(NSInteger fromSection, NSInteger toSection); /**< 检查是否允许跨secton操作，未设置则默认允许 */
@property (nonnull, copy) void(^cjCellMoveCompleteBlock)(NSIndexPath *sourceIndexPath, NSIndexPath *destinationIndexPath); /**< 移动结束的回调 */

@end

@implementation UICollectionView (CJLongPressMove)

#pragma mark - runtime GestureRecognizer
// cjMoveGestureRecognizer
- (UILongPressGestureRecognizer *)cjMoveGestureRecognizer {
    return objc_getAssociatedObject(self, @selector(cjMoveGestureRecognizer));
}

- (void)setCjMoveGestureRecognizer:(UILongPressGestureRecognizer *)cjMoveGestureRecognizer {
    objc_setAssociatedObject(self, @selector(cjMoveGestureRecognizer), cjMoveGestureRecognizer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

#pragma mark - runtime Block
//cjCheckSectionMoveEnableBlock
- (BOOL (^)(NSIndexPath * _Nonnull))cjCheckSectionMoveEnableBlock {
    return objc_getAssociatedObject(self, (__bridge const void *)(cjCheckSectionMoveEnableBlockKey));
}

- (void)setCjCheckSectionMoveEnableBlock:(BOOL (^)(NSIndexPath * _Nonnull))cjCheckSectionMoveEnableBlock {
    objc_setAssociatedObject(self, (__bridge const void *)(cjCheckSectionMoveEnableBlockKey), cjCheckSectionMoveEnableBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

//cjCheckCellMoveEnableBlock
- (BOOL (^)(NSInteger fromSection, NSInteger toSection))cjCheckCellMoveEnableBlock {
    return objc_getAssociatedObject(self, (__bridge const void *)(cjCheckCellMoveEnableBlockKey));
}

- (void)setCjCheckCellMoveEnableBlock:(BOOL (^)(NSInteger fromSection, NSInteger toSection))cjCheckCellMoveEnableBlock {
    objc_setAssociatedObject(self, (__bridge const void *)(cjCheckCellMoveEnableBlockKey), cjCheckCellMoveEnableBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

// cjCellMoveCompleteBlock
- (void (^)(NSIndexPath *sourceIndexPath, NSIndexPath *destinationIndexPath))cjCellMoveCompleteBlock {
    return objc_getAssociatedObject(self, @selector(cjCellMoveCompleteBlock));
}

- (void)setCjCellMoveCompleteBlock:(void (^)(NSIndexPath *sourceIndexPath, NSIndexPath *destinationIndexPath))cjCellMoveCompleteBlock {
    objc_setAssociatedObject(self, @selector(cjCellMoveCompleteBlock), cjCellMoveCompleteBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

#pragma mark - Event
/*
*  移除长按拖动手势
*/
- (void)cj_removeLongPressMoveGR {
    if (self.cjMoveGestureRecognizer) {
        [self removeGestureRecognizer:self.cjMoveGestureRecognizer];
    }
}

/*
*  为列表添加长按手势，利用手势的开始、变化、结束实现拖动
*
*   @param minimumPressDuration 手势相应的最短按住时长(比如已经是抖动了，就可以设置为短一点)
*/
- (void)cj_addLongPressMoveGR:(NSTimeInterval)minimumPressDuration {
    UILongPressGestureRecognizer *moveGR = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(__cjMoveGRAction:)];
    moveGR.minimumPressDuration = minimumPressDuration;
    [self addGestureRecognizer:moveGR];
    self.cjMoveGestureRecognizer = moveGR;
}

/*
*  设置拖动手势Move各个过程的回调等
*
*  @param checkSectionMoveEnableBlock   设置允许哪些section中的哪些item进行拖动操作，未设置则默认都允许
*  @param checkCellMoveEnableBlock      检查是否允许跨secton操作，未设置则默认允许
*  @param cellMoveCompleteBlock         移动结束的回调
*/
- (void)cj_setupCheckSectionMoveEnableBlock:(BOOL (^ __nullable)(NSIndexPath *indexPath))checkSectionMoveEnableBlock
                   checkCellMoveEnableBlock:(BOOL (^ __nullable)(NSInteger fromSection, NSInteger toSection))checkCellMoveEnableBlock
                      cellMoveCompleteBlock:(void(^ __nullable)(NSIndexPath *sourceIndexPath, NSIndexPath *destinationIndexPath))cellMoveCompleteBlock
{
    self.cjCheckSectionMoveEnableBlock = checkSectionMoveEnableBlock;
    self.cjCheckCellMoveEnableBlock = checkCellMoveEnableBlock;
    self.cjCellMoveCompleteBlock = cellMoveCompleteBlock;
}



#pragma mark - UICollectionViewDataSource
//开启collectionView可以移动
- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath {
    if (self.cjCheckSectionMoveEnableBlock) {
        return self.cjCheckSectionMoveEnableBlock(indexPath);
    }
    
    return YES;
}

//处理collectionView移动过程中的数据操作
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
    //NSLog(@"移动完毕");
    !self.cjCellMoveCompleteBlock ?: self.cjCellMoveCompleteBlock(sourceIndexPath, destinationIndexPath);
}




#pragma mark - Private Method
/// 拖动过程中的监听
- (void)__cjMoveGRAction:(UILongPressGestureRecognizer *)moveLongPressGR {
    static NSInteger fromSection = 0;    // 记录section，防止跨section移动
    static NSInteger lastSection = 0;
    
    //判断手势落点位置是否在row上
    CGPoint longPressLocationPoint = [moveLongPressGR locationInView:self];
    NSIndexPath *indexPath = [self indexPathForItemAtPoint:longPressLocationPoint];
    switch (moveLongPressGR.state) {
        case UIGestureRecognizerStateBegan:
        {
            //手势开始
            if (indexPath == nil) {
                //NSLog(@"手势落点位置没落在哪个indexPath位置上");
                break;
            }
            
            UICollectionViewCell *cell = [self cellForItemAtIndexPath:indexPath];
            [self bringSubviewToFront:cell];
            //iOS9 方法 移动cell
            [self beginInteractiveMovementForItemAtIndexPath:indexPath];
            fromSection = indexPath.section;
            lastSection = indexPath.section;
        
            break;
        }
        case UIGestureRecognizerStateChanged:
        {
            NSInteger toSection = 0;
            if (indexPath == nil) {
                toSection = lastSection;
            } else {
                toSection = indexPath.section;
            }
            lastSection = toSection;
            
            BOOL moveEnable = self.cjCheckCellMoveEnableBlock == nil || self.cjCheckCellMoveEnableBlock(fromSection, toSection);
            if (moveEnable) {
                //iOS9 方法 移动过程中随时更新cell位置
                [self updateInteractiveMovementTargetPosition:longPressLocationPoint];
            } else {
                NSString *message = [NSString stringWithFormat:@"不能从%zd区移动到%zd区", fromSection, toSection];
                NSLog(@"温馨提示:%@", message);
            }
            break;
        }
        case UIGestureRecognizerStateEnded:
        {
            //手势结束
            //iOS9方法 移动结束后关闭cell移动
            [self endInteractiveMovement];
            break;
        }
        default:
        {
            //取消移动
            [self cancelInteractiveMovement];
            break;
        }
    }
}

@end
